package net.ojbk.sso.center.beans.pojo;

import com.alibaba.fastjson.JSONObject;
import net.ojbk.sso.center.beans.po.ClientWebsite;
import net.ojbk.sso.center.beans.vo.VO_LoggedWebsites;
import net.ojbk.sso.center.exception.TokenSystemException;
import net.ojbk.sso.core.beans.dto.DTO_TO_Client;
import net.ojbk.sso.core.util.HttpClientSimpleTool;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: twobox
 * Date: 2019/3/23
 * Time: 21:29
 * Description: 用户登陆对象!!!说白了，就像是cookies->HttpSession。的token->UserLogin
 * 负责一个用户对所有子网站会话的管理
 */
@Component
public class OjbkSession {
    private static Logger logger = Logger.getLogger(OjbkSession.class);

    // cookies->HttpSession
    // token->OjbkSession
    private HttpSession session;
    private String token;
    private Set<ClientWebsite> clientWebsiteSet;

    // 0 构造器
    private OjbkSession() {
    }

    public static OjbkSession createNewOjbkSession(HttpSession session, String token) {
        OjbkSession ojbkSession = new OjbkSession();
        ojbkSession.session = session;
        ojbkSession.token = token;
        ojbkSession.clientWebsiteSet = new HashSet<ClientWebsite>();
        session.setAttribute("token", token);
        return ojbkSession;
    }

    // 1 动作
    // 1.1 登陆一个网站
    public void addOneClientWebsite(ClientWebsite clientWebsite) {
        session.setMaxInactiveInterval(-1);
        clientWebsiteSet.add(clientWebsite);
    }

    // 1.2 注销所有网站
    public void logoutAllWebsite() throws Exception {
        for (ClientWebsite website : this.clientWebsiteSet
        ) {
            DTO_TO_Client requestClient = new DTO_TO_Client(website.getServiceKey(), DTO_TO_Client.TYPE_LOGOUT, token);
            JSONObject jsonObject = HttpClientSimpleTool.post(website.getClientUrl(), requestClient);
            if (jsonObject == null)
                logger.info("请求注销失败：" + website);
        }
        // 注销处理
        this.session.removeAttribute("token");
        this.session = null;
        this.clientWebsiteSet = null;
        this.token = null;
    }

    // **** 1.3 1、保证Center网站HttpSession时间长于子网站2、。如何本session已失效将会抛出异常。3、如果返回状态不为OK，这删除该Website.
    public void maintainAllClientWebsite() throws Exception {
        // 只要存在子网站处于登陆状态，则本Session过期为-1。否则为6分钟失效。
        // 及时清理已注销的子网站
        String token = (String) session.getAttribute("token");
        if (token == null || token.equals(""))
            throw new IllegalStateException("Session失效：Session中，token为null或空");

        for (ClientWebsite website : this.clientWebsiteSet) {
            DTO_TO_Client requestClient = new DTO_TO_Client(website.getServiceKey(), DTO_TO_Client.TYPE_IS_INVALID, token);
            JSONObject jsonObject = HttpClientSimpleTool.post(website.getClientUrl(), requestClient);
            boolean isInvalid = jsonObject.getBooleanValue("data");
            logger.debug("Get " + token + "'s invalid situation for " + website.getCname());
            if (isInvalid)
                this.clientWebsiteSet.remove(website);
        }
        if (this.clientWebsiteSet.isEmpty())
            this.session.setMaxInactiveInterval(60 * 30);
        else
            this.session.setMaxInactiveInterval(-1);
    }


    // 2 相关信息获取
    public String getToken() {
        return this.token;
    }

    public HttpSession getHttpSession() {
        return this.session;
    }

    public List<VO_LoggedWebsites> getAllLoggedWeb() {
        List<VO_LoggedWebsites> vo_loggedWebsites = new ArrayList<>();
        for (ClientWebsite website : this.clientWebsiteSet) {
            vo_loggedWebsites.add(new VO_LoggedWebsites(website.getCname(), website.getClientUrl()));
        }
        return vo_loggedWebsites;
    }

    // 3 工具方法
    // 3.1 删除一个网站，而不是发信息去注销一个网站。也就是说remove一个set对象
    private void removeOneClientWebsite(ClientWebsite clientWebsite) {
        clientWebsiteSet.remove(clientWebsite);
    }

}
